package com.spring.framework.config.autowired.model;

import lombok.ToString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

/**
 * 注解@Autowired在按照类型无法选择唯一的依赖注入时（比如存在多个类型兼容或者相同的候选依赖），可以使用Spring的@Primary注
 * 解，@Primary注解表示当有多个bean是该类型依赖项的候选对象时，应该优先考虑特定的被@Primary注解修饰的bean。
 * <p>
 * 注解@Primary类似于XML装配中的primary属性，区别是：XML装配中的primary是绑定到一个bean上面的，而@Primary注解装配则是绑
 * 定到类上面的。
 * <p>
 * 如果同一个类型（包括兼容类型）的不同bean中有超过一个bean被标注了@Primary注解。那么如果是采用方法注入或者字段注入或者采用
 * 构造器注入并且required=true，在运行时将直接抛出异常: available: more than one ‘primary’ bean found among candidates……
 * 如果采用构造器注入并且required=false，那么将不会选择该构造器，最终可能会选择无参构造器，即不注入该依赖，如果没有其他构造器
 * 可选，那么同样抛出异常。
 * <p>
 * 使用了@Primary注解，那么就不会走后面根据name匹配的逻辑，如果@Primary注解无法筛选出唯一的依赖，那么直接抛出异常或者不注
 * 入该依赖（上面讲了）。
 *
 * @author xuweizhi
 * @since 2020/12/15 11:23
 */
@ToString
@Component
public class AutowiredPrimaryDemo {

	/**
	 * 优先注入 @Primary 注解修饰的类
	 */
	@Autowired
	private NullablePrimaryA nullablePrimaryA;

	@Component("nullablePrimaryA")
	public static class NullablePrimaryA {
		public NullablePrimaryA() {
			System.out.println("NullableDemoA：" + this);
		}
	}

	/**
	 * 选择主要依赖,注入该类型 bean，优先选择该类
	 */
	@Primary
	@Component("nullablePrimaryB")
	public static class NullablePrimaryB extends NullablePrimaryA {
		public NullablePrimaryB() {
			System.out.println("NullableDemoB：" + this);
		}
	}
}
